#ifndef _VOLUME3D_H
#define _VOLUME3D_H
#include <stdio.h>
#include <string>
#include "slice2D.h"

class volume3D
{
public:
	//volume3D(const char *filename, int z, int y, int x, int);
	volume3D(const char* filename, int z, int y, int x, int voxelByteSize, bool delayLoad=false);
	volume3D(void *data, int z, int y, int x, int voxelByteSize);
	volume3D(int z, int y, int x, int voxelByteSize, int value); //create empty volume
	~volume3D();

	
	//generater
	volume3D* generateVolume16bitTo8bit();
	volume3D* generateUpSampleVolume();
	volume3D* generateDownSampleVolume();
	volume3D* generateDownSampleVolumeNN();
	volume3D* generateDownSampleVolumeWithBoundaryNN();

	volume3D* generateSubVolume(double minZ, double maxZ,
													    double minY, double maxY,
													    double minX, double maxX);
	volume3D* generateSubVolume(int minZ, int maxZ,
													    int minY, int maxY,
													    int minX, int maxX);

	volume3D* generateOctBlock(int z, int y, int x, bool boundary);

	//slice generater/modifer
	slice2D* generateSliceX(int index, int minY, int maxY, int minX, int maxX);
	slice2D* generateSliceY(int index, int minY, int maxY, int minX, int maxX);
	slice2D* generateSliceZ(int index, int minY, int maxY, int minX, int maxX);

	void updateSliceX(slice2D* slice, int index, int minY, int maxY, int minX, int maxX);
	void updateSliceY(slice2D* slice, int index, int minY, int maxY, int minX, int maxX);
	void updateSliceZ(slice2D* slice, int index, int minY, int maxY, int minX, int maxX);

	//volume modifer
	bool addSubVolume(volume3D* vol, int z, int y, int x);
	//TODO
	//bool clearSubRegion(int min
	void updateBoundaryToUpperLevelBlock(volume3D* upperLevel, int zp, int zn, int yp, int yn, int xp, int xn); //x:0,1 y:0,1 z:0,1 
	//accesser
	int getVoxelByteSize();
	unsigned int getVoxel(int z, int y, int x);
	unsigned int getVoxel(double z, double y, double x);
	unsigned int getVoxelNN(double z, double y, double x);
	int getDimX();
	int getDimY();
	int getDimZ();

	void generateVirtualDim(int);
	int getVirtualDimX();
	int getVirtualDimY();
	int getVirtualDimZ();
	void* getDataBuffer();

	//modifer
	bool setVoxel(int z, int y, int x, unsigned int value);

	//status
	void 	updateMaxMin();
	unsigned int getMin();
	unsigned int getMax();
	void calculateMean();
	unsigned int getMean();



	//debug
	bool writeToFile(const char* filename);


private:
	std::string _filename;
	
	int _voxelByteSize;
	void *_data;

	int _dimX, _dimY, _dimZ;
	int _virtualDimX, _virtualDimY, _virtualDimZ;
	unsigned int _min, _max, _mean;

	bool _isDelay;
	FILE *pFile; 

	
};

#endif